home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
PARI
/
PARI2
/
pari
/
c
/
arith2
< prev
next >
Wrap
Text File
|
1991-12-14
|
32KB
|
1,189 lines
/*********************************************************************/
/*********************************************************************/
/** **/
/** FONCTIONS ARITHMETIQUES **/
/** **/
/** (deuxieme partie) **/
/** **/
/** copyright Babe Cool **/
/** **/
/** **/
/*********************************************************************/
/*********************************************************************/
#include "genpari.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~ ~*/
/*~ NOMBRES PREMIERS ~*/
/*~ ~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GEN prime (n)
long n;
{
byteptr p=diffptr;
long c,prime=0;
while (n--) if (c= *p++) prime += c; else err(primer1);
return stoi(prime);
}
GEN primes (n)
long n;
{
GEN y,z;
byteptr p=diffptr;
long c,prime=0;
z=y=cgetg(n+1,17);
while (n--)
{
if (c= *p++) prime+=c; else err(primer1);
*++z=(long)stoi(prime);
}
return y;
}
byteptr initprimes(maxnum)
long maxnum;
{
register long k,size=(maxnum+257)>>1;
byteptr p=(byteptr)calloc(size,1);
register byteptr q,r,s,fin=p+size;
for(r=q=p,k=1;r<fin;)
{
do {r+=k; k+=2; r+=k;} while (*++q);
for(s=r;s<fin;s+=k) *s=1;
}
r=p; *r++=2; *r++=1;
for(s=q=r-1;;)
{
while (*++q);
if (q>=fin) break;
*r++=(q-s)<<1;
s=q;
}
*r++=0;
return (byteptr)realloc(p,r-p);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~ ~*/
/*~ FONCTIONS ARITHMETIQUES DE BASE ~*/
/*~ ~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Attention, le parametre doit etre une variable. */
#define pseudoprime(p) millerrabin(p,5*lgef(p))
long mu(n)
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN p, f;
long av=avma,s=1;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return 1;
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
if (divise(n,p)) {avma=av;return 0;}
s= -s;
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1)||(lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0)||pseudoprime(f))) f=ellfacteur(f);
diviiz(n,f,n);
if (divise(n,f)) {avma=av;return 0;}
s= -s;
}
avma=av;
return s;
}
GEN phi(n)
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN f,p,m;
long av1,av2;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return stoi(1);
m=cgeti(lgef(n));affsi(1,m);
av1=avma;
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
muliiz(m,subis(p,1),m);
while (mpdivis(n,p,n)) muliiz(m,p,m);
if ((n[2]==1)&&(lgef(n)==3)) break;
avma=av2;
}
while ((n[2]!=1) || (lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0) || pseudoprime(f))) f = ellfacteur(f);
mpdivis(n,f,n);
muliiz(m,subis(f,1),m);
while (mpdivis(n,f,n)) muliiz(m,f,m);
avma=av2;
}
avma=av1;
return m;
}
GEN auxdecomp(n,all)
GEN n; long all;
{
byteptr d=diffptr;
unsigned char c;
GEN p,z,p1,p2,f;
long nb=0,j,k,lim,av1,av2,av3,av4,sn;
if (typ(n)!=1) err(arither1);
if (!(sn=signe(n))) err(arither2);
if(sn<0) {stoi(-1);stoi(1);nb++;}
if ((n[2]!=1) || (lgef(n)!=3))
{
av1=avma;
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;lim=(all<=1)?VERYBIGINT:all;
while ((c= *d++)&&(p[2]<=lim))
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
nb++;
for (k=1;mpdivis(n,p,n);k++);
gcopy(p);
stoi(k);
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1)||(lgef(n)!=3))
{
av3=avma;
f=n;
if(all==1)
while (!((cmpii(mulii(p,p),f)>0)||pseudoprime(f))) f=ellfacteur(f);
av4=avma;
f=gerepile(av3,av4,gcopy(f));
nb++;
for (k=0;mpdivis(n,f,n);k++);
stoi(k);
}
gerepile(av1,av2,0);
}
p=(GEN)avma;
z=cgetg(3,19);
p1=cgetg(nb+1,18);z[1]=(long)p1;
p2=cgetg(nb+1,18);z[2]=(long)p2;
for (j=nb;j;j--)
{
p2[j]=(long)p;
p+=lg(p);
p1[j]=(long)p;
p+=lg(p);
}
return z;
}
GEN decomp(n)
GEN n;
{
return auxdecomp(n,1);
}
GEN smallfact(n)
GEN n;
{
GEN p1,p2,p3,p4,p5,y;
long av,tetpil;
switch(typ(n))
{
case 1:return auxdecomp(n,0);
case 5:av=avma;n=gred(n);
case 4:if(typ(n)==4) av=avma;p1=auxdecomp(n[1],0);
p2=auxdecomp(n[2],0);p4=concat(p1[1],p2[1]);
p5=concat(p1[2],gneg(p2[2]));p3=indexsort(p4);
tetpil=avma;y=cgetg(3,19);y[1]=(long)extract(p4,p3);
y[2]=(long)extract(p5,p3);return gerepile(av,tetpil,y);
default: err(arither1);
}
}
GEN boundfact(n,lim)
GEN n;
long lim;
{
GEN p1,p2,p3,p4,p5,y;
long av,tetpil;
if(lim<=1) lim=0;
switch(typ(n))
{
case 1:return auxdecomp(n,lim);
case 5:av=avma;n=gred(n);
case 4:if(typ(n)==4) av=avma;p1=auxdecomp(n[1],lim);
p2=auxdecomp(n[2],lim);p4=concat(p1[1],p2[1]);
p5=concat(p1[2],gneg(p2[2]));p3=indexsort(p4);
tetpil=avma;y=cgetg(3,19);y[1]=(long)extract(p4,p3);
y[2]=(long)extract(p5,p3);return gerepile(av,tetpil,y);
default: err(arither1);
}
}
GEN divisors(n)
GEN n;
{
long tetpil,av=avma,i,j,l,start;
GEN p,t=decomp(n),p1=(GEN)t[1],p2=(GEN)t[2],t1,t2,t3,nbdiv=gun;
l=lg(p1);
start=1+((l>1)&&(signe(p1[1])<0));
for(i=start;i<l;i++)nbdiv=mulis(nbdiv,1+itos(p2[i]));
p=t=cgetg(itos(nbdiv)+1,17);
*++p=lstoi(1);
for(i=start;i<l;i++)
for(t1=t,j=itos(p2[i]);j;j--)
{
t2=p;
for(t3=t1;t3<t2;)
*++p=lmulii(*++t3,p1[i]);
t1=t2;
}
tetpil=avma;
return gerepile(av,tetpil,sort(t));
}
long omega(n)
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN p,f;
long nb=0,av=avma,av2;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return 0;
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
nb++;
while (mpdivis(n,p,n));
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1) || (lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0)||pseudoprime(f))) f=ellfacteur(f);
nb++;
while (mpdivis(n,f,n));
avma=av2;
}
avma=av;
return nb;
}
long bigomega(n)
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN p,f;
long nb=0,av=avma,av2;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return 0;
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
do nb++;while (mpdivis(n,p,n));
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1) || (lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0) || pseudoprime(f))) f = ellfacteur(f);
while (mpdivis(n,f,n)) nb++;
avma=av2;
}
avma=av;
return nb;
}
GEN numbdiv(n)
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN p,f,m,m1;
long l,av=avma,av2,av3;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return stoi(1);
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;
m=stoi(1);
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
for (l=2;mpdivis(n,p,n);l++);
av3=avma;
m1=mulsi(l,m);
if (lgef (m1) ==lgef(m)) affii(m1,m);
else m=gerepile(av2,av3,m1);
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1) || (lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0) || pseudoprime(f))) f = ellfacteur(f);
for (l=2;mpdivis(n,f,n);l++);
av3=avma;
m=gerepile(av2,av3,mulsi(l,m));
}
return gerepile(av,av2,m);
}
GEN sumdiv(n)
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN p,f,m,m1;
long av1=avma,av2,av3;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return stoi(1);
n=absi(n);
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;
m=gun;
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
m1=addsi(1,p);
while (mpdivis(n,p,n)) m1=addsi(1,mulii(p,m1));
av3=avma;m=gerepile(av2,av3,mulii(m1,m));
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1)||(lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0)||pseudoprime(f))) f=ellfacteur(f);
m1=gun;
while (mpdivis(n,f,n)) m1=addsi(1,mulii(f,m1));
av3=avma;m=gerepile(av2,av3,mulii(m1,m));
}
return gerepile(av1,av2,m);
}
GEN sumdivk(k,n)
long k;
GEN n;
{
byteptr d=diffptr;
unsigned char c;
GEN p,p1,f,m,m1,pk;
long av1=avma,av2,av3,k1;
if (typ(n)!=1) err(arither1);
if (!signe(n)) err(arither2);
if ((n[2]==1)&&(lgef(n)==3)) return stoi(1);
n=absi(n);k1=k;if(k<0) {k= -k;p1=gpuigs(n,k1);}
p=cgeti(3);p[1]=0x1000003;p[2]=0;
av2=avma;
m=gun;
while (c= *d++)
{
p[2]+=c;
if (!mpdivis(n,p,n)) continue;
pk=gpuigs(p,k);
m1=addsi(1,pk);
while (mpdivis(n,p,n)) m1=addsi(1,mulii(pk,m1));
av3=avma;m=gerepile(av2,av3,mulii(m1,m));
if ((n[2]==1)&&(lgef(n)==3)) break;
}
while ((n[2]!=1)||(lgef(n)!=3))
{
f=gcopy(n);
while (!((cmpii(mulii(p,p),f)>0)||pseudoprime(f))) f=ellfacteur(f);
pk=gpuigs(f,k);
m1=gun;
while (mpdivis(n,f,n)) m1=addsi(1,mulii(pk,m1));
av3=avma;m=gerepile(av2,av3,mulii(m1,m));
}
av3=avma;return (k1>=0) ? gerepile(av1,av2,m) : gerepile(av1,av3,gmul(p1,m));
}
/* decomposition de nombres par la methode des courbes elliptiques.
La seule fonction exportee est ellfacteur.
Cette fonction renvoie un facteur non trivial de n.
On suppose en entree que n n'est pas premier, et n'est divisible par
aucun petit nombre premier (pas de facteur<65536,en tout cas.) */
static GEN x1,y11,x2,y2,aux,w,n,global;
static long nombre,taillef;
static GEN cree(nb)
long nb;
{
GEN z=cgetg(nb+1,17);
long i;
for(i=1;i<=nb;i++) z[i]=lgeti(taillef);
return z;
}
static long pur(x,p)
long x,*p;
{
byteptr d=diffptr;
long m=0;
do m+= *d++;while (x % m);
do x /=m;while (!(x % m));
*p=m;
return x==1;
}
static GEN elladd()
{
GEN v1,glob,lambda;
long i,av=avma;
for(i=1;i<=nombre;i++)
{subiiz(x1[i],x2[i],aux[i]); if (signe(aux[i])<0) addiiz(aux[i],n,aux[i]);}
for(i=1;i<=nombre;i++)
{modiiz(mulii(aux[i],w[i]),n,w[i+1]);avma=av;}
if (!inversemodulo(w[nombre+1],n,&glob)) return glob;
affii(glob,global);
for(i=nombre;i;i--)
{
v1=modii(mulii(global,w[i]),n);
modiiz(mulii(global,aux[i]),n,global);
lambda=modii(mulii(subii(y11[i],y2[i]),v1),n);
modiiz(subii(mulii(lambda,lambda),addii(x2[i],x1[i])),n,x2[i]);
modiiz(subii(mulii(lambda,subii(x1[i],x2[i])),y11[i]),n,y2[i]);
avma=av;
}
return (GEN)0;
}
static GEN elldouble()
{
GEN v1,v2,glob,lambda;
long i,av=avma;
for(i=1;i<=nombre;i++) {modiiz(shifti(y2[i],1),n,aux[i]);avma=av;}
for(i=1;i<=nombre;i++) {modiiz(mulii(aux[i],w[i]),n,w[i+1]);avma=av;}
if (!inversemodulo(w[nombre+1],n,&glob)) return glob;
affii(glob,global);
for(i=nombre;i;i--)
{
v1=modii(mulii(global,w[i]),n);
modiiz(mulii(global,aux[i]),n,global);
lambda=modii(mulii(addsi(1,mulsi(3,mulii(x2[i],x2[i]))),v1),n);
v2=modii(subii(mulii(lambda,lambda),shifti(x2[i],1)),n);
modiiz(subii(mulii(lambda,subii(x2[i],v2)),y2[i]),n,y2[i]);
affii(v2,x2[i]);
avma=av;
}
return (GEN)0;
}
static GEN ellmult(k)
long k;
{
GEN result = (GEN)0;
if (k>1)
{
if (result = ellmult(k/2)) return result;
if (result = elldouble()) return result;
if (k&1) result = elladd();
}
return result;
}
GEN ellfacteur(n1)
GEN n1;
{
static long i,k,m,av;
static GEN glob;
taillef=lgef(n1);
nombre=10*lgef(n1);
global=cgeti(taillef);
av=avma;
n=absi(n1);
x1=cree(nombre);
x2=cree(nombre);
y11=cree(nombre);
y2=cree(nombre);
aux=cree(nombre);
w=cree(nombre+1);
w[1]=un;
for(i=nombre;i;i--) {affsi(rand(),x2[i]);affsi(rand(),y2[i]);}
for (m=2;;m++)
if (pur(m,&k))
{
for(i=nombre;i;i--) {affii(x2[i],x1[i]);affii(y2[i],y11[i]);}
if(glob = ellmult(k))
{
if (cmpii(mulii(glob,glob),n)>0) diviiz(n,glob,global);
else affii(glob,global);
avma=av;
return global;
}
}
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~ ~*/
/*~ COMPOSITION DES FORMES QUADRATIQUES ~*/
/*~ ~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GEN qfi(x, y, z)
GEN x, y, z;
{
GEN t;
if((typ(x)!=1)||(typ(y)!=1)||(typ(z)!=1)) err(qfer1);
t=cgetg(4,16);
t[1] = lcopy(x); t[2] = lcopy(y); t[3] = lcopy(z);
return t;
}
GEN qfr(x, y, z, d)
GEN x, y, z, d;
{
GEN t;
if((typ(x)!=1)||(typ(y)!=1)||(typ(z)!=1)||(typ(d)!=2)) err(qfer1);
t=cgetg(5,15);
t[1]=lcopy(x);t[2]=lcopy(y);t[3]=lcopy(z);t[4]=lcopy(d);
return t;
}
GEN compose(x,y)
GEN x,y;
{
long av,tetpil;
GEN s,n,d,d1,d2,x1,x2,y1,y2,v1,v2,v3,b3,c3,m,z,p1,r;
if(cmpii(x[1],y[1])>0) {s=x;x=y;y=s;}
av=avma;s=shifti(addii(x[2],y[2]),-1);n=subii(y[2],s);
d=bezout(y[1],x[1],&y1,&x1);d1=bezout(s,d,&x2,&y2);
v1=divii(x[1],d1);v2=divii(y[1],d1);
d2=(gcmp1(d1))?gun:mppgcd(d1,mppgcd(x[3],mppgcd(y[3],n)));
v3=mulii(d2,v1);
m=addii(mulii(mulii(y1,y2),n),mulii(y[3],x2));setsigne(m,-signe(m));
r=modii(m,v3);b3=shifti((p1=mulii(v2,r)),1);
c3=addii(mulii(y[3],d1),mulii(r,addii(y[2],p1)));
z=cgetg(4,16);z[1]=lmulii(v3,v2);z[2]=laddii(y[2],b3);z[3]=ldivii(c3,v3);
tetpil=avma;return gerepile(av,tetpil,redcomp(z));
}
GEN compreal(x,y)
GEN x,y;
{
long av,tetpil;
GEN s,n,d,d1,d2,x1,x2,y1,y2,v1,v2,v3,b3,c3,m,z,p1,r;
av=avma;s=shifti(addii(x[2],y[2]),-1);n=subii(y[2],s);
d=bezout(y[1],x[1],&y1,&x1);d1=bezout(s,d,&x2,&y2);
v1=divii(x[1],d1);v2=divii(y[1],d1);
d2=(gcmp1(d1))?gun:mppgcd(d1,mppgcd(x[3],mppgcd(y[3],n)));
v3=mulii(d2,v1);
m=addii(mulii(mulii(y1,y2),n),mulii(y[3],x2));setsigne(m,-signe(m));
r=modii(m,v3);b3=shifti((p1=mulii(v2,r)),1);
c3=addii(mulii(y[3],d1),mulii(r,addii(y[2],p1)));
z=cgetg(5,15);z[1]=lmulii(v3,v2);z[2]=laddii(y[2],b3);z[3]=ldivii(c3,v3);
z[4]=laddrr(x[4],y[4]);tetpil=avma;return gerepile(av,tetpil,redreal(z));
}
GEN comprealraw(x,y)
GEN x,y;
{
long av,tetpil;
GEN s,n,d,d1,d2,x1,x2,y1,y2,v1,v2,v3,b3,c3,m,z,p1,r;
av=avma;s=shifti(addii(x[2],y[2]),-1);n=subii(y[2],s);
d=bezout(y[1],x[1],&y1,&x1);d1=bezout(s,d,&x2,&y2);
v1=divii(x[1],d1);v2=divii(y[1],d1);
d2=(gcmp1(d1))?gun:mppgcd(d1,mppgcd(x[3],mppgcd(y[3],n)));
v3=mulii(d2,v1);
m=addii(mulii(mulii(y1,y2),n),mulii(y[3],x2));setsigne(m,-signe(m));
r=modii(m,v3);b3=shifti((p1=mulii(v2,r)),1);
c3=addii(mulii(y[3],d1),mulii(r,addii(y[2],p1)));
z=cgetg(5,15);z[1]=lmulii(v3,v2);z[2]=laddii(y[2],b3);z[3]=ldivii(c3,v3);
z[4]=laddrr(x[4],y[4]);tetpil=avma;return gerepile(av,tetpil,gcopy(z));
}
GEN nucomp(x,y,l)
GEN x,y,l;
/* l=floor((|d|/4)^(1/4)) */
{
long av=avma,tetpil,cz;
GEN s,n,d,d1,v,u1,u,v1,v2,z,p1,p2,p3;
GEN a,b,e,f,g,a1,a2,a3,b3,v3,q,t2,t3,c3,q1,q2,q3,q4;
if((typ(x)!=16)||(typ(y)!=16)) err(nucomper1);
if(x==y) return nudupl(x,l);
if(cmpii(x[1],y[1])<0) {s=x;x=y;y=s;}
s=shifti(addii(x[2],y[2]),-1);n=subii(y[2],s);
a1=(GEN)x[1];a2=(GEN)y[1];d=bezout(a2,a1,&u,&v);
if(gcmp1(d)) {a=negi(gmul(u,n));d1=d;}
else
if(divise(s,d))
{
a=negi(gmul(u,n));d1=d;a1=divii(a1,d1);a2=divii(a2,d1);s=divii(s,d1);
}
else
{
d1=bezout(s,d,&u1,&v1);
if(!gcmp1(d1))
{
a1=divii(a1,d1);a2=divii(a2,d1);s=divii(s,d1);d=divii(d,d1);
}
p1=resii(x[3],d);p2=resii(y[3],d);
p3=modii(negi(mulii(u1,addii(mulii(u,p1),mulii(v,p2)))),d);
a=subii(mulii(p3,divii(a1,d)),mulii(u,divii(n,d)));
}
a=modii(a,a1);p1=subii(a1,a);if(cmpii(a,p1)>0) a=negi(p1);
v=gzero;d=a1;v2=gun;v3=a;cz=0;
while(cmpii(v3,l)>=0)
{
q=dvmdii(d,v3,&t3);t2=subii(v,mulii(q,v2));
v=v2;d=v3;v2=t2;v3=t3;cz++;
}
if(!cz)
{
q1=mulii(a2,v3);q2=addii(q1,n);f=divii(q2,d);
g=divii(addii(mulii(v3,s),y[3]),d);
a3=mulii(d,a2);c3=addii(mulii(v3,f),mulii(g,d1));
b3=addii(shifti(q1,1),y[2]);
}
else
{
if(cz&1) {v3=negi(v3);v2=negi(v2);}
b=divii(addii(mulii(a2,d),mulii(n,v)),a1);q1=mulii(b,v3);
q2=addii(q1,n);f=divii(q2,d);
e=divii(addii(mulii(s,d),mulii(y[3],v)),a1);
q3=mulii(e,v2);q4=subii(q3,s);g=divii(q4,v);
if(!gcmp1(d1)) {v2=mulii(d1,v2);v=mulii(d1,v);}
a3=addii(mulii(d,b),mulii(e,v));c3=addii(mulii(v3,f),mulii(g,v2));
b3=addii(addii(q1,q2),mulii(d1,addii(q3,q4)));
}
z=cgetg(4,16);z[1]=(long)a3;z[2]=(long)b3;z[3]=(long)c3;
tetpil=avma;return gerepile(av,tetpil,redcomp(z));
}
GEN nudupl(x,l)
GEN x,l;
/* l=floor((|d|/4)^(1/4)) */
{
long av=avma,tetpil,cz;
GEN u,v,d,d1,p1,a,b,c,b2,z,v2,v3,q,t2,t3,e,g;
d1=bezout(x[2],x[1],&u,&v);a=divii(x[1],d1);b=divii(x[2],d1);
c=modii(negi(mulii(u,x[3])),a);p1=subii(a,c);if(cmpii(c,p1)>0) c=negi(p1);
v=gzero;d=a;v2=gun;v3=c;cz=0;
while(cmpii(v3,l)>=0)
{
q=dvmdii(d,v3,&t3);t2=subii(v,mulii(q,v2));
v=v2;d=v3;v2=t2;v3=t3;cz++;
}
if(!cz)
{
g=divii(addii(mulii(b,v3),x[3]),d);
z=cgetg(4,16);z[1]=lmulii(d,d);
z[2]=laddii(x[2],shifti(mulii(d,v3),1));
z[3]=laddii(mulii(v3,v3),mulii(g,d1));
}
else
{
if(cz&1) {v=negi(v);d=negi(d);}
e=divii(addii(mulii(x[3],v),mulii(b,d)),a);
g=divii(subii(mulii(e,v2),b),v);b2=addii(mulii(e,v2),mulii(v,g));
if(!gcmp1(d1)) {b2=mulii(d1,b2);v=mulii(d1,v);v2=mulii(d1,v2);}
z=cgetg(4,16);z[1]=laddii(mulii(d,d),mulii(e,v));
z[2]=laddii(b2,shifti(mulii(d,v3),1));
z[3]=laddii(mulii(v3,v3),mulii(g,v2));
}
tetpil=avma;return gerepile(av,tetpil,redcomp(z));
}
GEN sqcomp(x)
GEN x;
{
long av,tetpil;
GEN d1,d2,x2,y2,v1,v3,b3,c3,m,z,p1,r;
av=avma;
d1=bezout(x[2],x[1],&x2,&y2);v1=divii(x[1],d1);
d2=(gcmp1(d1))?gun:mppgcd(d1,x[3]);v3=mulii(d2,v1);
m=mulii(x[3],x2);setsigne(m,-signe(m));
r=modii(m,v3);b3=shifti((p1=mulii(v1,r)),1);
c3=addii(mulii(x[3],d1),mulii(r,addii(x[2],p1)));
z=cgetg(4,16);z[1]=lmulii(v3,v1);
z[2]=laddii(x[2],b3);z[3]=ldivii(c3,v3);
tetpil=avma;return gerepile(av,tetpil,redcomp(z));
}
GEN sqcompreal(x)
GEN x;
{
long av,tetpil;
GEN d1,d2,x2,y2,v1,v3,b3,c3,m,z,p1,r;
av=avma;
d1=bezout(x[2],x[1],&x2,&y2);v1=divii(x[1],d1);
d2=(gcmp1(d1))?gun:mppgcd(d1,x[3]);v3=mulii(d2,v1);
m=mulii(x[3],x2);setsigne(m,-signe(m));
r=modii(m,v3);b3=shifti((p1=mulii(v1,r)),1);
c3=addii(mulii(x[3],d1),mulii(r,addii(x[2],p1)));
z=cgetg(5,15);z[1]=lmulii(v3,v1);z[2]=laddii(x[2],b3);z[3]=ldivii(c3,v3);
z[4]=lshiftr(x[4],1);tetpil=avma;return gerepile(av,tetpil,redreal(z));
}
GEN sqcomprealraw(x)
GEN x;
{
long av,tetpil;
GEN d1,d2,x2,y2,v1,v3,b3,c3,m,z,p1,r;
av=avma;
d1=bezout(x[2],x[1],&x2,&y2);v1=divii(x[1],d1);
d2=(gcmp1(d1))?gun:mppgcd(d1,x[3]);v3=mulii(d2,v1);
m=mulii(x[3],x2);setsigne(m,-signe(m));
r=modii(m,v3);b3=shifti((p1=mulii(v1,r)),1);
c3=addii(mulii(x[3],d1),mulii(r,addii(x[2],p1)));
z=cgetg(5,15);z[1]=lmulii(v3,v1);z[2]=laddii(x[2],b3);z[3]=ldivii(c3,v3);
z[4]=lshiftr(x[4],1);tetpil=avma;return gerepile(av,tetpil,gcopy(z));
}
GEN powrealraw(x,n,prec)
GEN x;
long n,prec;
{
long av,tetpil;
GEN p1,p2,y,z;
if(n<0) err(impl,"powrealraw for negative exponents");
if(n==1) return gcopy(x);
z=x;av=avma;y=cgetg(5,15);y[1]=un;
p1=subii(mulii(x[2],x[2]),shifti(mulii(x[1],x[3]),2));
p2=racine(p1);if(mpodd(subii(p2,x[2]))) p2=addsi(-1,p2);
y[2]=(long)p2;y[3]=lshifti(subii(mulii(p2,p2),p1),-2);
p1=cgetr(prec);y[4]=(long)p1;p1[1]=0x800000-((prec-2)<<5);
p1[2]=0;tetpil=avma;y=gerepile(av,tetpil,gcopy(y));
if(!n) return y;
else
{
for(;n>1;n>>=1)
{
if (n&1) y=comprealraw(y,z);
z=sqcomprealraw(z);
}
tetpil=avma;return gerepile(av,tetpil,comprealraw(y,z));
}
}
GEN nupow(x,n)
GEN x,n;
{
long av,tetpil,i,j;
unsigned long m;
GEN p1,p2,y,z,l;
if(typ(n)!=1) err(nupower1);
if(gcmp1(n)) return gcopy(x);
z=x;av=avma;y=cgetg(4,16);y[1]=un;y[2]=mpodd(x[2]) ? un : zero;
p1=mulii(x[1],x[3]);p2=shifti(mulii(x[2],x[2]),-2);y[3]=lsubii(p1,p2);
if(!signe(n)) {tetpil=avma;return gerepile(av,tetpil,gcopy(y));}
else
{
l=racine(shifti(racine(y[3]),1));
for (i=lgef(n)-1;i>2;i--)
{
for (m=n[i],j=0;j<32;j++,m>>=1)
{
if (m&1) y=nucomp(y,z,l);
z=nudupl(z,l);
}
}
for (m=n[2];m>1;m>>=1)
{
if (m&1) y=nucomp(y,z,l);
z=nudupl(z,l);
}
tetpil=avma;y=nucomp(y,z,l);
if ((signe(n)<0)&&cmpii(y[1],y[2])&&cmpii(y[1],y[3]))
setsigne(y[2],-signe(y[2]));
y=gerepile(av,tetpil,y);
}
}
GEN redcomp(x)
GEN x;
{
long av,tetpil,s,fl,fg;
GEN b1,c1,p1,a,b,c,d,z;
av=avma;a=(GEN)x[1];b=(GEN)x[2];c=(GEN)x[3];
fl=cmpii(a,c);s=signe(b);setsigne(b,abs(s));fg=cmpii(a,b);
while((fl>0)||(fg<0))
{
p1=shifti(c,1);d=dvmdii(b,p1,&b1);
setsigne(b,s);
if(s>=0)
{
if(cmpii(b1,c)<=0) {setsigne(d,-signe(d));setsigne(b1,-signe(b1));}
else {d=subsi(-1,d);b1=subii(p1,b1);}
}
else
{
if(cmpii(b1,c)>=0) {d=addsi(1,d);b1=subii(b1,p1);}
}
c1=addii(a,mulii(d,shifti(subii(b,b1),-1)));a=c;
b=b1;c=c1;
fl=cmpii(a,c);s=signe(b);setsigne(b,abs(s));fg=cmpii(a,b);
}
if(fl&&fg&&(s<0)) setsigne(b,s);tetpil=avma;
z=cgetg(4,16);z[1]=lcopy(a);z[2]=lcopy(b);z[3]=lcopy(c);
return gerepile(av,tetpil,z);
}
GEN rhoreal(x)
GEN x;
{
long av,tetpil,s,l;
GEN y,p1,nn,sqrtD,isqrtD,D;
if(typ(x)!=15) err(rhoer1);
av=avma;y=cgetg(5,15);
l=max(lg(x[4]),((-expo(x[4]))>>5)+2);if(l<=2) l=3;
y[1]=lcopy(x[3]);sqrtD=gsqrt(D=subii(mulii(x[2],x[2]),shifti(mulii(x[1],x[3]),2)),l);
isqrtD=mptrunc(sqrtD);
s=signe(y[1]);setsigne(y[1],1);
if(cmpii(isqrtD,y[1])>=0) nn=divii(addii(isqrtD,x[2]),p1=shifti(y[1],1));
else nn=divii(addii(y[1],x[2]),p1=shifti(y[1],1));
p1=mulii(nn,p1);y[2]=lsubii(p1,x[2]);
setsigne(y[1],s);p1=shifti(subii(mulii(y[2],y[2]),D),-2);y[3]=ldivii(p1,y[1]);
y[4]=laddrr(shiftr(mplog(absr(divrr(addir(x[2],sqrtD),subir(x[2],sqrtD)))),-1),x[4]);
tetpil=avma;return gerepile(av,tetpil,gcopy(y));
}
GEN redreal(x)
GEN x;
{
long fl,av=avma,tetpil,l,s;
GEN y,p1,sqrtD,isqrtD,D,z,nn;
if(typ(x)!=15) err(rhoer1);
if(signe(x[4])) l=lg(x[4]);
else {l=((-expo(x[4]))>>5)+2;if(l<=2) l=3;}
sqrtD=gsqrt(D=subii(mulii(x[2],x[2]),shifti(mulii(x[1],x[3]),2)),l);
isqrtD=mptrunc(sqrtD);
y=cgetg(5,15);y[1]=x[1];y[2]=x[2];y[3]=x[3];y[4]=x[4];
if((signe(x[2])<=0)||(cmpii(x[2],isqrtD)>0)) fl=1;
else
{
p1=subii(isqrtD,shifti(absi(x[1]),1));
if(signe(p1)<0) fl=(cmpii(x[2],absi(p1))<0);else fl=(cmpii(x[2],p1)<=0);
}
while(fl)
{
z=cgetg(5,15);
z[1]=y[3];s=signe(z[1]);setsigne(z[1],1);
if(cmpii(isqrtD,z[1])>=0) nn=divii(addii(isqrtD,y[2]),p1=shifti(z[1],1));
else nn=divii(addii(z[1],y[2]),p1=shifti(z[1],1));
p1=mulii(nn,p1);z[2]=lsubii(p1,y[2]);
setsigne(z[1],s);p1=shifti(subii(mulii(z[2],z[2]),D),-2);z[3]=ldivii(p1,z[1]);
z[4]=laddrr(shiftr(mplog(absr(divrr(addir(y[2],sqrtD),subir(y[2],sqrtD)))),-1),y[4]);
y=z;
if((signe(y[2])<=0)||(cmpii(y[2],isqrtD)>0)) fl=1;
else
{
p1=subii(isqrtD,shifti(absi(y[1]),1));
if(signe(p1)<0) fl=(cmpii(y[2],absi(p1))<0);else fl=(cmpii(y[2],p1)<=0);
}
}
tetpil=avma;return gerepile(av,tetpil,gcopy(y));
}
GEN rhorealnod(x,isqrtD)
GEN x,isqrtD;
{
long av,tetpil,s;
GEN y,p1,nn,D;
if(typ(x)!=15) err(rhoer1);
if(typ(isqrtD)!=1) err(arither1);
av=avma;y=cgetg(5,15);
y[1]=lcopy(x[3]);D=subii(mulii(x[2],x[2]),shifti(mulii(x[1],x[3]),2));
s=signe(y[1]);setsigne(y[1],1);
if(cmpii(isqrtD,y[1])>=0) nn=divii(addii(isqrtD,x[2]),p1=shifti(y[1],1));
else nn=divii(addii(y[1],x[2]),p1=shifti(y[1],1));
p1=mulii(nn,p1);y[2]=lsubii(p1,x[2]);
setsigne(y[1],s);p1=shifti(subii(mulii(y[2],y[2]),D),-2);y[3]=ldivii(p1,y[1]);
affsr(0,y[4]=lgetr(3));
tetpil=avma;return gerepile(av,tetpil,gcopy(y));
}
GEN redrealnod(x,isqrtD)
GEN x,isqrtD;
{
long fl,av=avma,tetpil,s;
GEN y,p1,D,z,nn;
if(typ(x)!=15) err(rhoer1);
if(typ(isqrtD)!=1) err(arither1);
D=subii(mulii(x[2],x[2]),shifti(mulii(x[1],x[3]),2));
y=cgetg(5,15);y[1]=x[1];y[2]=x[2];y[3]=x[3];
if((signe(x[2])<=0)||(cmpii(x[2],isqrtD)>0)) fl=1;
else
{
p1=subii(isqrtD,shifti(absi(x[1]),1));
if(signe(p1)<0) fl=(cmpii(x[2],absi(p1))<0);else fl=(cmpii(x[2],p1)<=0);
}
while(fl)
{
z=cgetg(5,15);
z[1]=y[3];s=signe(z[1]);setsigne(z[1],1);
if(cmpii(isqrtD,z[1])>=0) nn=divii(addii(isqrtD,y[2]),p1=shifti(z[1],1));
else nn=divii(addii(z[1],y[2]),p1=shifti(z[1],1));
p1=mulii(nn,p1);z[2]=lsubii(p1,y[2]);
setsigne(z[1],s);p1=shifti(subii(mulii(z[2],z[2]),D),-2);z[3]=ldivii(p1,z[1]);
y=z;
if((signe(y[2])<=0)||(cmpii(y[2],isqrtD)>0)) fl=1;
else
{
p1=subii(isqrtD,shifti(absi(y[1]),1));
if(signe(p1)<0) fl=(cmpii(y[2],absi(p1))<0);else fl=(cmpii(y[2],p1)<=0);
}
}
affsr(0,y[4]=lgetr(3));
tetpil=avma;return gerepile(av,tetpil,gcopy(y));
}
GEN primeform(x,p,prec)
GEN x,p;
long prec;
{
long av,tetpil,s,t,sb,sx=signe(x);
GEN y,b,c;
if((typ(x)!=1)||(!sx)) err(arither1);
if(gcmpgs(p,2))
{
y=(sx<0) ? cgetg(4,16) : cgetg(5,15);y[1]=lcopy(p);y[2]=lgeti(lgef(p));
av=avma;
if(!mpsqrtmod(x,p,&b)) err(sqrter5);
s=b[lgef(b)-1]&1;t=x[lgef(x)-1]&1;
if(odd(s+t)) subiiz(p,b,y[2]);else affii(b,y[2]);
c=shifti(subii(mulii(y[2],y[2]),x),-2);tetpil=avma;
y[3]=lpile(av,tetpil,divii(c,p));
}
else
{
s=x[lgef(x)-1]&7;if(signe(x)<0) s=8-s;
switch(s)
{
case 0:
case 8: sb=0;break;
case 1: sb=1;break;
case 4: sb=2;break;
default: err(sqrter5);
}
y=(sx<0) ? cgetg(4,16) : cgetg(5,15);y[1]=lcopy(deux);y[2]=lstoi(sb);
av=avma;c=gsubsg(sb*sb,x);tetpil=avma;
y[3]=lpile(av,tetpil,shifti(c,-3));
}
if(sx>0) affsr(0,y[4]=lgetr(prec));
return y;
}
GEN classno(x)
GEN x;
/* calcul de h(x) pour x<0 par la methode de Shanks */
{
static long prem,ptforme;
long av,av1,av2,av3,tetpil,k,k2,i,j,j1,lim,limite,succes,com,j2,s;
GEN tabla, tablb, count, index, hash;
static long court[3]={0x1000003,0x1010003,0};
GEN p1,p2,p3,hin,q,formes[100],l,h,hp,f,fh,fg,ftest,pm2;
static byteptr p;
if (typ(x)!=1) err(arither1);
if (!(s=signe(x))) err(arither2);
if(s>0) return classno2(x);
k=x[lgef(x)-1]&3;
if((k==1)||(k==2)) err(classer2);
if(gcmpgs(x,-12)>=0) return gun;
tabla = newbloc(10000);
tablb = newbloc(10000);
count = newbloc(256);
index = newbloc(257);
hash = newbloc(10000);
prem=ptforme=0;p=diffptr;av=avma;limite=(av+bot)>>1;
p1=divrr(gsqrt(absi(x),4),mppi(4));
l=gtrunc(shiftr(gsqrt(gsqrt(absi(x),4),4),1));
if(gcmpgs(l,1000)<0) affsi(1000,l);
while((gcmpgs(l,prem)>=0)&&(*p))
{
prem+= *p++;
k=krogs(x,prem);
if(k)
{
av2=avma;
if(k>0)
{
divrsz(mulsr(prem,p1),prem-1,p1);avma=av2;
if((ptforme<100)&&(prem>2))
{
court[2]=prem;
formes[ptforme++]=redcomp(primeform(x,court,3));
}
}
else {divrsz(mulsr(prem,p1),prem+1,p1);avma=av2;}
}
}
hin=ground(p1);h=gcopy(hin);f=formes[0];fh=gpui(f,h);
s=2*itos(gceil(gpui(p1,gdivgs(gun,4),4)));
if(s>=10000) s=10000;
p1=fh;av2=avma;
for(i=0;i<=255;i++) count[i]=0;
for(i=0;i<=s-1;i++)
{
p2=(GEN)p1[1];tabla[i]=p2[lgef(p2)-1];j=tabla[i]&255;count[j]++;
p2=(GEN)p1[2];tablb[i]=p2[lgef(p2)-1];
p1=compose(p1,f);
}
fg=gpuigs(f,s);ftest=gpuigs(p1,0);
index[0]=0;for(i=0;i<=254;i++) index[i+1]=index[i]+count[i];
for(i=0;i<=s-1;i++) hash[index[tabla[i]&255]++]=i;
index[0]=0;for(i=0;i<=255;i++) index[i+1]=index[i]+count[i];
succes=0;com=0;av3=avma;
while(!succes)
{
p1=(GEN)ftest[1];k=p1[lgef(p1)-1];j=k&255;
pm2=negi(ftest[2]);
for(j1=index[j];(j1<index[j+1])&&(!succes);j1++)
{
j2=hash[j1];
if(tabla[j2]==k)
{
p2=(GEN)ftest[2];k2=p2[lgef(p2)-1];
if((tablb[j2]==k2)||(tablb[j2]== -k2))
{
p1=gmul(gpuigs(f,j2),fh);
succes=(!cmpii(p1[1],ftest[1]))&&((!cmpii(p1[2],ftest[2]))||(!cmpii(p1[2],pm2)));
}
}
}
if(!succes)
{
com++;
if(avma>=limite) ftest=gmul(ftest,fg);
else {tetpil=avma;ftest=gerepile(av3,tetpil,gmul(ftest,fg));}
if (gcmp1(ftest[1]))
{
err(impl, "classno with too small order");
}
}
}
h=addis(h,j2);p2=mulsi(s,stoi(com));tetpil=avma;
h=(!cmpii(p1[2],ftest[2]))?subii(h,p2):addii(h,p2);
p2=factor(h);
p1=(GEN)p2[1];
p2=(GEN)p2[2];
for(i=1;i<lg(p1);i++)
{
p3=divii(h,p1[i]);fh=gpui(f,p3);lim=itos(p2[i]);
for(j=1;(j<=lim)&&(!cmpii(fh[1],un));j++)
{
h=p3;
if(j<lim) {p3=divii(h,p1[i]);fh=gpui(f,p3);}
}
}
q=ground(gdiv(hin,h));tetpil=avma;
hp=mulii(q,h);av1=avma;
for(i=1;(i<=10)&&(i<ptforme);i++)
{
f=formes[i];com=0;
fg=gpui(f,h);
fh=gpui(fg,q);
ftest=fg;
if(cmpis(fh[1],1))
{
for(;;)
{
com++;
if ((!cmpii(fh[1],ftest[1]))&&((!cmpii(fh[2],ftest[2]))||(!cmpii(fh[2],negi(ftest[2]))))) break;
ftest=gmul(ftest,fg);
}
if(!cmpii(fh[2],ftest[2])) com= -com;
p2=mulsi(com,h);q=addsi(com,q);tetpil=avma;
hp=addii(hp,p2);av1=avma;
}
}
avma=av1;
killbloc(tabla); killbloc(tablb); killbloc(count);
killbloc(index); killbloc(hash);
return gerepile(av,tetpil,hp);
}